//This file a version used for submitting individual parts as well as fixing quickly fixing incompatibilities. It involves editing other members' code to make things run smoothly in a short amount of time.
//THE ORDER OF THE FRAGMENTS IS IMPORTANT. PLEASE RETAIN IT IF AT ALL POSSIBLE.
//EVERYTHING WAS REWRITTEN BY CORNELL WASHINGTON

#include "Menu.h" //most of the needed headers are already defined here
#include <iostream>

//additional includes
#include <sstream>
#include <cstdlib> //required in order to use atoi()
#include <algorithm> //required in order to use sort()
#include <iomanip> //required in order to use setprecision() and setw()
#include <assert.h>

using namespace std;

Menu::Menu()
{
}

void Menu::display_main_menu() const //We need to figure out how to keep this from appearing when "Exit" is chosen
{
	cout<<"+-------------------------------------------------------+\n";
	cout<<"|          Restaurant Order Management System           |\n";
        cout<<"|                        Group 4                        |\n";
        cout<<"|               Please choose an option:                |\n";
        cout<<"+-----------------+-------------------+-----------------+\n";
        cout<<"| 1: Information  |  2: Read file in  | 3: Show queries |\n";
        cout<<"+-----------------+-------------------+-----------------+\n";
        cout<<"| 4: Find queries | 5: Update queries | 6: Exit Program |\n";
        cout<<"+-----------------+-------------------+-----------------+\n";
}
void Menu::display_info() const //NEEDS MORE INFO
{
	cout << "Here is the Info requested: \n";
	cout << "This is a Restaurant Order Management System (ROMS). "
		<< "\nThis program implements a simple “character oriented” menu-driven user interface."
		<< "\nCreated by Adam Dewitt, Austin Martin, and Cornell Washington."
		<<"\nHey, our names are perfectly alphabetical! :P\n";

}
void Menu::read()
{	
	//-----------------------------Cornell Washington's Suggested A1------------------------------
	//Clear all vectors for reading
	categories.clear();
	menu_items.clear();
	recipes.clear();
	ingredients.clear();
	orders.clear();
	order_items.clear();
	//This should work a little better
	string r_name = "recipes.dat"; //file to be opened
	ifstream ist(r_name.c_str());
	
	if(!ist) throw InvalidFile();
	
	int num_ingredients, ingredient_id, recipe_id, amount_req = 0; //initialized to zero
	string units, name, chef_name = "\0"; //null strings
	char ch = '\0'; //null char
	string instructions = "\0";
	
	ist >> num_ingredients; //read in the number of ingredients
	int M3 = num_ingredients; //used for loop
	string rs; //used for getline
	
	bool tf = true; //used for loop
	
	while(ist)
	{	
		getline(ist,rs);
		if(ingredients.size() < M3)
		{
			ist >> ingredient_id >> recipe_id, amount_req, units, name; //read in ingredient data
			
			Ingredient i(ingredient_id, recipe_id, amount_req, units, name); //create ingredient
			ingredients.push_back(i); //store ingredient
		}
		else if(tf)
		{
			num_ingredients = 0;
			ist >> num_ingredients; //get new number of records
			tf = false;
		}
		else if(recipes.size() < num_ingredients)
		{

			instructions.clear(); //clear string
			ist >> recipe_id >> chef_name; //read in recipe data
			while(ist.get(ch) && ch != '#') //read in instructions
			{
				instructions += ch;
			}
			Instructions instruct;
			instruct.instr = instructions; //store instuctions
			
			Recipe r(recipe_id, chef_name, instruct); //create recipe
			recipes.push_back(r); //store recipe
		}
	}
	ist.close(); //close file (possibly uneeded)
	cout << "\nRecipe and Instructions data loaded.";
	//------------------------------------------End A1--------------------------------------------
	
	//-----------------------------Cornell Washington's Suggested A2------------------------------
	//This is a more compatible method. I recommend doing it this way to simplify things.
	//	--Alright, after further inspection of my own code, I found that this part may not need rewriting.
	//	--I'll have to perform more testing
	int order_N, M2, table_id, server_id, order_id, seat_id, menu_item_id, quantity_ordered, year, month, day, hour, minute = 0; //set to zero just in case
	menu_item_id = 0;
	//YYYY, MM, DD format will be used.
	
	string o_ifname = "orders.dat";
	ifstream order_stream(o_ifname.c_str());
	
	char ch_o = '\0'; //null char
	
	if(!order_stream) throw InvalidFile();
	
	order_stream >> order_N; //read in number of records

	string os; //used for getline
	M2 = order_N; //used for loop
	
	tf = true; //used for loop
	
	while (order_stream)
	{
		getline(order_stream, os); //Move to next line
		if(orders.size() < M2)
		{
			order_stream >> order_id >> server_id >> table_id >> year >> month >> day >> hour >> minute; //read in order data
			Chrono::Date::Month m = Chrono::Date::Month(month); //create date data
			Chrono::Date d(year,m,day);
			Clock::Time t; //create time data
			t.add_hour(hour);
			t.add_minutes(minute);
			Order o(order_id, server_id, table_id, d, t); //create order
			orders.push_back(o); //store order
		}
		else if(tf)
		{
			order_N = 0;
			order_stream >> order_N; //read in new number of records
			tf = false;
		}
		else if(order_items.size() < order_N)
		{
			order_stream >> ch_o >> order_id >> menu_item_id >> quantity_ordered; //read in order item data
			
			seat_id = ch_o; //Convert char to int (may not be necessary)
			Order_Item oi(seat_id, order_id, menu_item_id, quantity_ordered); //create order item
			order_items.push_back(oi); //store order item
		}

	}
	order_stream.close(); //close file
	cout << "\nOrder and Order Item data loaded.";
	//------------------------------------------End A2--------------------------------------------
	
	//-----------------------------------------Begin A3-------------------------------------------
	//Section written by Cornell Washington
	//Read and store category and menu item data from catmenu.dat

	string fname = "catmenu.dat";

	ifstream ist1(fname.c_str());
	Description ds;

	char ch1 = '\0';

	//These vectors are probably already declared elsewhere...
	vector<string> vdesc; //Descriptions
	vector<string> vinames; //Item Names

	vector<int> vmid; //Menu IDs

	vector<string> vcate; //Category names
	vector<int> vcid; //Category IDs

	vector<int> vrid; //Recipe IDs
	vector<double> vprices; //Hmmmm...

	vector<Description> vdescriptions;

	int cat_N, M, menu_id, cat_id, rec_id, price = 0; //cat_N is for the number of records, M is to help with the if-statements
	string cat_name, descr, item_name = "\0"; //Strings for the category names, descriptions, and item names
	Description des;

	if (!ist1)
	{
		throw InvalidFile();
	}
	ist1 >> cat_N; //read in number of records
	string s; //used for getline
	M = cat_N; //used for loop
	tf = true; //Boolean to help with the if-statements

	while (ist1){
		
		getline(ist1,s); //This is required for some odd reason. The application hangs without it.
		
		if (categories.size() < M)
		{
			ist1 >> cat_id >> cat_name; //read in category data

			Category cat(cat_id,cat_name); //create category
			categories.push_back(cat); //store category

		}
		else if (tf)
		{
			cat_N = 0;
			ist1 >> cat_N; //read in new number of records
			tf = false;
		}
		else if (vmid.size() < cat_N)
		{
			descr = "\0"; //clear string
			ist1 >> menu_id >> cat_id >> rec_id >> item_name >> price; //read in menu item data
			while(ist1.get(ch1) && ch1 != '#') //read in descriptions
			{
				descr += ch1;
				des.desc = descr;
			}

			vmid.push_back(menu_id); //store menu item data
			vrid.push_back(rec_id);
			vcid.push_back(cat_id);
			vinames.push_back(item_name);
			vprices.push_back(price);
			vdesc.push_back(descr);
			vdescriptions.push_back(des);
		}
	}
	ist1.close();
	for (int i = 0; i < cat_N; i++)
	{
		Menu_Item mi(vmid[i],vcid[i],vrid[i],vinames[i],vprices[i],vdescriptions[i]); //create menu items
		menu_items.push_back(mi); //store menu items
	}
	
	cout << "\nCategory and Menu data loaded.\n";
//---------------------------------------------End A3-----------------------------------------------------------
//--------------------------------------------Begin D3-----------------------------------------------
//In the merged code, verify category, order, recipe and menu item IDs are unique.
//Written by Cornell Washington
	cout << "Performing sanity check...\n";
	vector<int> cat_id_c, order_id_c, rec_id_c, menu_item_id_c; //Vectors used for sanity check
	for (int i = 0; i < categories.size(); i++)
	{
		cat_id_c.push_back(categories[i].get_cid());
		for(int j = 0; j < categories.size(); j++)
		{
			if (i != j)
			{
				if (categories[j].get_cid() == cat_id_c[i])
				{
					throw DuplicateID();
				}
			}
		}
	}
	for (int i = 0; i < orders.size(); i++)
	{
		order_id_c.push_back(orders[i].get_oid());
		for (int j = 0; j < orders.size(); j++)
		{
			if (i != j){
				if(orders[j].get_oid() == order_id_c[i])
				{
					throw DuplicateID();
				}
			}
		}
	}
	for (int i = 0; i < recipes.size(); i++)
	{
		rec_id_c.push_back(recipes[i].get_rec_id());
		for (int j = 0; j < recipes.size(); j++)
		{
			if (i != j)
			{
				if(recipes[j].get_rec_id() == rec_id_c[i])
				{
					throw DuplicateID();
				}
			}
		}
	}
	for (int i = 0; i < menu_items.size(); i++)
	{
		menu_item_id_c.push_back(menu_items[i].get_miid());
		for (int j = 0; j < menu_items.size(); j++)
		{
			if(i != j)
			{
				if(menu_items[j].get_miid() == menu_item_id_c[i])
				{
					throw DuplicateID();
				}
			}
		}
	}
	cout << "Sanity check completed successfully.\n";
	//We shouldn't have to worry about any ID conflicts after this point, since everything is dynamic.
//---------------------------------------------End D3------------------------------------------------

}
void Menu::show() const
{
	cout << "Show queries \n";
	cout << "\n";

	//----------------------------------Begin Section B.1 by Adam DeWitt---------------------------------------------
	//C1 is included as well
	cout << "Choose one of the following:\n";
    cout << "(a) Print a menu item recipe\n";
    cout << "(b) Print all menu items sorted by chef\n"; 
    cout << "(c) Print all menu items in a given category sorted by price\n"; 
	cout << "(d) Print all order IDs and tab price sorted by date\n"; 
    cout << "(e) Print all menu items in a given order sorted by price\n"; 
    cout << "> ";
	//WARNING: FOLLOWING CODE LIKELY TO BE BUGGY
	
	char choice;
	
	cin >> choice;
	choice = tolower(choice);
	//ERROR CHECKING NEEDED HERE
	
    if (choice == 'a') {
       cout << "\nAll menu items:\n\n";
		int umiid = 0;
       for (int i = 0; i < menu_items.size(); i++)
	   {
			cout << menu_items[i].get_miid() << ": " << menu_items[i].get_name() << '\n';
	   }
	   cout << "Choose an item by ID: ";
	   //Real error checking needed
	   cin >> umiid;
	   bool found = false;
	   //Menu_Item& mir; //reference to menu_item
	   int ref;
	   for (int i = 0; i < menu_items.size(); i++)
	   {
			if (umiid == menu_items[i].get_miid())
			{
				found = true;
				ref = i;
			}
	   }
	   
	   const Menu_Item& mir = menu_items[ref];
	   
	   if (found)
	   {
			bool found2 = false;
			int j = 0;
			for (int i = 0; i < recipes.size(); i++)
			{
				if (recipes[i].get_rec_id() == mir.get_rec_id())
				{
					found2 = true;
					j = i;
				}
			}
			if (found2)
			{
				cout << recipes[j].get_instr() << '\n';
			}
			else
			{
				throw InvalidData();
			}
			//cout << "menu_items[i].get_
	   }
	   else {cout << "Menu Item not found.\n";}
	   
	}
    else if(choice == 'b') {
       cout << "All menu items:\n";
       //Print all menu items sorted by chef; must associate menu_item with recipe

		vector<string> chefs;
	   vector<int> rec_ids;
		
	   for (int i = 0; i < recipes.size(); i++)
	   {
			chefs.push_back(recipes[i].get_chef_name());
	   }
	   cout << "Sorting...";
	   sort(chefs.begin(),chefs.end());
	   for (int i = 0; i < recipes.size(); i++)
	   {
			for (int j = 0; j < chefs.size(); j++)
			{	
				if(recipes[i].get_chef_name() == chefs[j])
				{
					rec_ids.push_back(recipes[i].get_rec_id());
					break;
				}
			}
	   }
	   cout << "\rDone.";
	   //assert(chefs.size() == rec_ids.size()); //speeds up debugging
	   cout << '\r';
	   for (int i = 0; i < chefs.size(); i++)
	   {
			cout << chefs[i] << ": ";
			
			bool found = false;
			for (int j = 0; j < menu_items.size(); j++)
			{
				if (menu_items[j].get_rec_id() == rec_ids[i])
				{
					found = true;
					cout << menu_items[j].get_name();
				}
			}
			if (!found)
			{
				cout << "[No associated menu item found]";
			}
			cout << '\n';
	   }
        cout << "\n";
    }
    else if(choice == 'c') {
        cout << "Categories:\n\n";
		//Print all menu items in a given category sorted by price; give category, then sort menu items by price
		for (int i = 0; i < categories.size(); i++)
		{
			cout << categories[i].get_cid() << ": " << categories[i].get_name() << '\n';
		}
		cout << "\nChoose a category (ID): ";
		int ucatid = 0;
		cin >> ucatid;
		
		vector<double> prices/*, menu_item_ids*/;
		
		bool found = false;
		
		for (int i = 0; i < menu_items.size(); i++)
		{
			if (ucatid == menu_items[i].get_cat_id())
			{
				found = true;
				prices.push_back(menu_items[i].get_price());
				//menu_item_ids.push_back(menu_items[i].get_miid());
			}
		}
		if (!found)
		{
			 cout << "No menu items in category.";
		}
		else
		{
			sort(prices.begin(),prices.end());
			for (int i = 0; i < menu_items.size(); i++)
			{
				for (int j = 0; j < prices.size(); j++)
				{
					if (prices[j] == menu_items[i].get_price())
					{
						//menu_item_id.push_back(menu_items[i].get_price());
						cout << menu_items[i].get_name() << ": " << prices[j] << '\n';
						break;
					}
				}
			}
		}
		
    }
	else if(choice == 'd'){
		//Print all order IDs and tab price sorted by date; print order IDs and prices, sorted by date (order_item)
		//Tab price = total price of all items in a certain order
		/*for (int i = 0; i < order_items.size(); i++)
		{
			
		}*/
	}
    else if(choice == 'e') {                    //Adam c1
        cout << "Enter an order ID: ";
		int order_id;
		cin >> order_id;
		bool found = false;
        //Print all menu items in a given order sorted by price; I'll just print the names and prices (order_item)
		for (int i = 0; i < orders.size(); i++)
		{
			if (order_id == orders[i].get_oid()) //also could have used order_items
			{
				found = true;
			}
		}
		if (!found)
		{
			cout << "Order ID not found.";
		}
		else
		{
			//bool found2 = false;
			vector<double> prices;
			//vector<int> menu_item_ids;
			
			for (int i = 0; i < order_items.size(); i++)
			{
				if (order_id == order_items[i].get_oid())
				{
					//found2 = true;
					for (int j = 0; j < menu_items.size(); j++)
					{
						if (order_items[i].get_miid() == menu_items[j].get_miid())
						{
							prices.push_back(menu_items[j].get_price());
							//menu_item_ids.push_back(menu_items[j].get_miid());
						}
					}
				}
			}
			
			sort(prices.begin(), prices.end());
			for (int i = 0; i < menu_items.size(); i++)
			{
				for (int j = 0; j < prices.size(); j++)
				{
					if (menu_items[i].get_price() == prices[j])
					{
						cout << menu_items[i].get_name() << ": " << prices[j] << '\n';
						break;
					}
				}
			}
		}
    }
	else { cout << "Invalid input.\n";}
	cout << "\n";

}
void Menu::find() const
{
	cout << "Find queries \n";
}
void Menu::update()
{
	cout << "Update queries \n";
	//--------------------------------------Begin B3--------------------------------------
	//Written by Cornell Washington
	bool added = false;
	
	for (int i = 0; i < categories.size(); i++) //used to avoid adding the categories multiple times
	{
		if (categories[i].added() && !added)
		{
			added = true;
		}
		
	}
	
	cout << "+----------------------------------------------------------------------+\n"; //pretty menu is pretty
	cout << "|               		Choose an item           	     	|\n";
	cout << "+----------------------------------------------------------------------+\n";
	cout << "|a: add new order item to existing order            			|\n";
	cout << "+----------------------------------------------------------------------+\n";
	cout << "|b: add new menu item to an existing category (using an unused recipe) |\n";
	cout << "+----------------------------------------------------------------------+\n";
	cout << "|c. add 'Soups', 'Salads', and 'Sides' to categories			|\n";
	cout << "+----------------------------------------------------------------------+\n";
	cout << "|d. add new order							|\n";
	cout << "+----------------------------------------------------------------------+\n";
	cout << "|e. add new menu item to an existing category       			|\n";
	cout << "+----------------------------------------------------------------------+\n";
	
	char mchoice = '\0';
	cout << "> "; //input
	cin >> mchoice;
	mchoice = tolower(mchoice); //Some like to use caps
	//Part A: Add new order item to existing order
	//Display all orders and the format of the order
	if (mchoice == 'a')
	{
		cout << "Here are all the existing orders: \n";
		cout << "Columns are 'Order ID,' 'Server ID,' and 'Table ID'\n";
		for (int i = 0; i < orders.size(); i++) //display all orders
		{
			string str_ord = orders[i].display();
			cout << " " << str_ord << '\n';
		}
		
		int uoid, umiid = 0; //user inputted order ID and menu item ID
		bool found = false;
		cout << "\nEnter the order ID of the order you would like to edit: ";
		cin >> uoid; //read in order ID
		char seatID = '\0'; //seat ID (character)
		int serverID = 0;
		int iseatID; //seat ID (integer)
		
		while(!found) //search for order
		{
			for (int i = 0; i < orders.size(); i++)
			{
				if (orders[i].get_oid() == uoid)
				{
					found = true;
					serverID = orders[i].get_sid();
				}
			}
			if(!found) //ask for new order ID
			{
				cout << "\nOrder not found. Try again: ";
				cin >> uoid;
			}
		}
		
		found = false; //recycle boolean
		
		cout << "Enter the Seat ID: ";
		cin >> seatID; //read in seat ID
		seatID = toupper(seatID); //convert to caps
		iseatID = seatID; //convert char to int
		bool valid = false;
		while(!valid) //Range check
		{
			if (iseatID < 65 || iseatID > 72)
			{
				cout << "Invalid seat ID. Try again: ";
				cin >> seatID;
				seatID = toupper(seatID);
				iseatID = seatID;
			}
			else {valid = true;}
		} 
			
		cout << "Enter the quantity ordered: ";
		int quant_o;
		cin >> quant_o; //read in quantity ordered
		valid = false; //recycle boolean
		while(!valid)
		{
			if (quant_o < 1 || quant_o > 256)
			{
				cout << "Invalid quantity. Try again: ";
				cin >> quant_o;
				
			} //Range check (upper bound may be removed)
			else
			{
				valid = true;
			}
		}
		
		cout << "Enter the Menu Item ID to be added to the order: ";
		cin >> umiid; //read in menu item ID
		
		while (!found) //search for menu item
		{
			for (int i = 0; i < menu_items.size(); i++)
			{
				if (umiid == menu_items[i].get_miid())
				{
					found = true;
					cout << menu_items[i].get_name() << " added to order " << uoid << '\n'; 
					Order_Item oi(iseatID, uoid, umiid, quant_o); //add menu item to order
					order_items.push_back(oi);	
				}
			}
			if (!found)
			{
				cout << "\nMenu item not found. Try again: ";
				cin >> umiid;
			}
		}
	}
	//Part B: Add a new menu item (using an existing recipe) to an existing category
	//Display all existing recipes that are not on the menu, as well as all existing categories
	else if (mchoice == 'b') 
	{
		vector<int> recIDs; //recipe IDs
		vector<int> matched; //matched IDs
		vector<int> stray; //nonmatched IDs
		
		bool found;
		
		for (int i = 0; i < recipes.size(); i++)
		{
			found = false;
			recIDs.push_back(recipes[i].get_rec_id()); //read in recipe IDs
			for (int j = 0; j < menu_items.size(); j++)
			{
				if(recipes[i].get_rec_id() == menu_items[j].get_rec_id()) //compare IDs
				{
					int mrid = recipes[i].get_rec_id();
					matched.push_back(mrid); //store in matched vector
					found = true;
				}
			}
			if (!found)
			{
				stray.push_back(recipes[i].get_rec_id()); //store in nonmatch vector
			}
		}
		
		if (stray.size() == 0) //check if recipes are available
		{
			cout << "No recipes are available.\n"; 
		}
		else
		{//----------------------------------------------------

			cout << "\nHere are the available recipes: ";
		
			for (int i = 0; i < stray.size(); i++) //list available recipes
			{
				cout << '\n' << stray[i];
			}
		
			cout << '\n';
		
			cout << "\nEnter a recipe ID: ";
			int r_id;
			cin >> r_id; //read in recipe ID
			bool found3 = false;
			while (!found3){ //check if available
				for (int i = 0; i < stray.size(); i++)
				{
					if (stray[i] == r_id)
					{
						found3 = true;
						break;
					}
				}
				if (!found3){ 
				
				cout << "\nRecipe not found or already in use.\nTry again: ";
				cin >> r_id;
				}
			}
		
			cout << "\nHere are the available categories: ";
		
			for (int i = 0; i < categories.size(); i++) //list available categories
			{
				cout << '\n' << categories[i].get_cid() << ": " << categories[i].get_name();
			}
			
			cout << '\n';
		
			cout << "\nChoose a category: ";
			int c_id;
			cin >> c_id; //read in category ID
			string c_name;
			bool found = false;
			while (!found) //search for category ID (messy)
			{
			for (int i = 0; i < categories.size(); i++)
			{
				if (categories[i].get_cid() == c_id)
				{	
					found = true;
					c_name = categories[i].get_name();
					cout << "Adding recipe #" << r_id  << " to '" << c_name << "'...";
				
					int m_id = 0; 
					for (int i = 0; i < menu_items.size(); i++) //dynamic menu item ID
					{
						if (menu_items[i].get_miid() > m_id)
						{
							m_id = menu_items[i].get_miid();
						}
					}
					++m_id; //set to be one greater than the others
					cout << "\nMenu item ID: " << m_id << '\n';
				
					string mi_name;
					cout << "\nEnter a name for the Menu Item (terminate with a semicolon(;)): ";
					char ch = '\0';
					while(cin.get(ch) && ch != ';') //read in name
					{
						mi_name += ch;
					}
					
					cout << "Type a description for the new menu item (terminate with '#'): ";
					Description d;
					ch = '\0';
					while(cin.get(ch) && ch != '#') //read in description
					{
						d.desc += ch;
					}
				
					double nprice;
					cout << "Enter a price: ";
					cin >> nprice; //read in price
				
					Menu_Item m_i(m_id,c_id,r_id,mi_name,nprice,d); //create menu item
					menu_items.push_back(m_i); //store menu item
					
					cout << "\nMenu Item added.\n";
				
					break;
				}
			
			}
			if(!found){ 
				cout << "\nCategory not found. Try again: ";
				cin >> c_id;
			}
			} //end while(!found)
		}//-----------------------------------------------------
	}
	
	//Part C: Add new categories: Soups, Salads, and Sides (this is to be added to the existing Appetizers, Entrees, Desserts, and Drinks)
	else if (mchoice == 'c') {
		if (!added){
			int sou_cid, sal_cid, sid_cid = 0;
			for (int i = 0; i < categories.size(); i++) //Dynamic category IDs; avoids need for another sanity check
			{
				if (categories[i].get_cid() > sou_cid) 
				{
					sou_cid = categories[i].get_cid();
				}
			}
			
			++sou_cid; //set to be one above the rest
			sal_cid = sou_cid+1;
			sid_cid = sal_cid+1;
			Category soups(sou_cid,"Soups");
			Category salads(sal_cid,"Salads");
			Category sides(sid_cid,"Sides");
			
			categories.push_back(soups);
			categories.push_back(salads);
			categories.push_back(sides);

			cout << "\nCategories updated.\n";
		}
		else {cout << "\nCategories have already been added.\n"; }
	}
	//---------------------------------------End B3---------------------------------------
	//--------------------------------------Begin C3--------------------------------------
	//Written by Cornell Washington
	//Part E: Add a new order given a server, table, date and time
	else if (mchoice == 'd')
	{
		int o_id; 
		for (int i = 0; i < orders.size(); i++) //Generate Order ID
		{
			if (orders[i].get_oid() > o_id)
			{
				o_id = orders[i].get_oid();
			}
		}
		o_id++; //set to be one greater than the others
		
		vector<int> tables; //raw vector of table IDs
		for (int i = 0; i < orders.size(); i++)
		{
			tables.push_back(orders[i].get_tid());
		}
		vector<int> servers; //raw vector of server IDs
		for (int i = 0; i < orders.size(); i++)
		{
			servers.push_back(orders[i].get_sid());
		}
		
		sort(servers.begin(),servers.end()); //sort data
		sort(tables.begin(),tables.end());
		
		vector<int> sclean; //vectors with duplicate data removed
		vector<int> tclean;
		
		for (int i = 0; i < tables.size(); i++) //remove duplicates
		{
			if(tables[i] != tables[i+1])
			{
				tclean.push_back(tables[i]);
			}
		}
		
		for (int i = 0; i < servers.size(); i++)
		{
			if(servers[i] != servers[i+1])
			{
				sclean.push_back(servers[i]);
			}
		}
		
		servers.clear();
		tables.clear(); //empty no longer used vectors to free up RAM
		
		cout << "\nHere are the available servers: \n";
		for (int i = 0; i < sclean.size(); i++) //list servers
		{
			cout << sclean[i] << '\n';
		}
		
		cout << "\nHere are the available tables: \n";
		for (int i = 0; i < tclean.size(); i++) //list tables
		{
			cout << tclean[i] << '\n';
		}
		
		int s_id = 0;
		bool good = false;
		bool found = false;
		
		while(!good){
			cout << "\nEnter server ID: ";
			cin >> s_id; 
		
			for (int i = 0; i < sclean.size(); i++) //check, but do not assert (add new server instead)
			{
				if(s_id == sclean[i]) found = true;
			}
			if (!found){
				bool valid = false;
				char ans;
				cout << "Server not found. Create? ";
				cin >> ans;
				ans = tolower(ans);
			
				while (!valid)
				{
					if (ans == 'n')
					{
						valid = true;
					}
					else if(ans == 'y')
					{
						valid = true;
						good = true;
						cout << "Server added.\n";
					}
					else
					{
						cout << "Invalid Input. Try again: ";
						cin >> ans;
						ans = tolower(ans);
					}
				}
			}
			else
			{
				good = true;
			}
		} //end while(!good)
		
		int t_id = 0;
		good = false;
		found = false;
		
		while(!good){
			cout << "\nEnter table ID: ";
			cin >> t_id; 
			
			for (int i = 0; i < tclean.size(); i++) //check, but do not assert (add new table instead)
			{
				if(t_id == tclean[i]) found = true;
			}
			if (!found){
				bool valid = false;
				char ans;
				cout << "Table not found. Create? ";
				cin >> ans;
				ans = tolower(ans); //convert to lower case
			
				while (!valid) //check input
				{
					if (ans == 'n')
					{
						valid = true;
					}
					else if(ans == 'y')
					{
						valid = true;
						good = true;
						cout << "Table added.\n";
					}
					else
					{
						cout << "Invalid Input. Try again: ";
						cin >> ans;
						ans = tolower(ans);
					}
				}
			}
			else
			{
				good = true;
			}
		} //end while(!good)
		
		//BUG: IF A NEW SERVER/TABLE WAS ADDED IN THE FUTURE, IT WILL BE AVAILABLE IN THE PAST
		//CAN BE AVOIDED BY SIMPLY ASSERTING THE SERVER/TABLE CHECK
		cout << "\nEnter date (year): "; //read in order date
		int d,mon,y;
		cin >> y;
		cout << "\nEnter date (month): ";
		cin >> mon;
		cout << "\nEnter date (day): ";
		cin >> d;
		cout << y << "/" << mon << "/" << d << '\n';
		Chrono::Date::Month mo = Chrono::Date::Month(mon);
		Chrono::Date da(y,mo,d);
		
		cout << "\nEnter time (hour, 0-23): "; //read in order time
		int h, m;
		cin >> h;
		cout << "\nEnter time (minute, 0-59): ";
		cin >> m;
		Clock::Time t;
		if (h > 23 || h < 0 || m < 0 || m > 59)
		{
			throw InvalidData();
		}
		else
		{	
			t.add_hour(h);
			t.add_minutes(m);
		}
		cout << setw(2) << setfill('0') << h << ":" << setw(2) << setfill('0') << m << '\n'; //make the time look proper
		
		Order o(o_id, s_id, t_id, da, t); //create order
		orders.push_back(o); //store order
		
		cout << "\nOrder added.\n";
	}
	//Part F: Add a new menu item to an existing category (assuming "new" means to create)
	else if (mchoice == 'e')
	{
		vector<int> recIDs; //recipe IDs
		double price = 0;
		int r_id, c_id, m_id = 0;
		string str = "\0";
		Description d;
		d.desc = "\0";
		
		for (int i = 0; i < recipes.size(); i++) //store recipe IDs
		{
			recIDs.push_back(recipes[i].get_rec_id()); 
		}
		
		cout << "\nHere are all the recipe IDs: \n";
		for (int i = 0; i < recIDs.size(); i++) //list recipe IDs
		{
			cout << recIDs[i] << '\n';
		}
		cout << "\nEnter a recipe ID: ";
		cin >> r_id; //read in recipe ID
		
		bool found = false;
		while (!found) //check if it exists
		{
			for (int i = 0; i < recIDs.size(); i++)
			{
				if (r_id == recIDs[i]) found = true;
			}
			if (!found)
			{
				cout << "\nRecipe ID not found. Try again: ";
				cin >> r_id;
			}
		}
		
		cout << "\nHere are all the categories: \n";
		for (int i = 0; i < categories.size(); i++) //list categories
		{
			cout << categories[i].get_cid() << ": " << categories[i].get_name() << '\n';
		}
		
		cout << "\nEnter a category ID: ";
		cin >> c_id; //read in category ID
		found = false;
		while (!found) //check if category exists
		{
			for (int i = 0; i < categories.size(); i++)
			{
				if (c_id == categories[i].get_cid()) found = true;
			}
			if (!found)
			{
				cout << "\nCategory not found. Try again: ";
				cin >> c_id;
			}
		}
		cout << "Enter a name for the new menu item (terminate with a semicolon (;)): ";
		
		char ch = '\0';
		while(cin.get(ch) && ch != ';') //read in name
		{
			str += ch;
		}
		
		cout << "Enter a decription for the new menu item (terminate with '#'): ";
		
		ch = '\0';
		while(cin.get(ch) && ch != '#') //read in description
		{
			d.desc += ch;
		}
		
		cout << "Enter a price for the menu item: ";
		cin >> price; //read in price
		
		for (int i = 0; i < menu_items.size(); i++) //dynamic menu item ID
		{
			if (menu_items[i].get_miid() > m_id)
			{
				m_id = menu_items[i].get_miid();
			}
		}
		++m_id; //set to be one greater than the others
		cout << "\nMenu item ID: " << m_id;
		
		Menu_Item mi(m_id, c_id, r_id, str, price, d); //create menu item
		menu_items.push_back(mi); //store menu item
		
		cout << "\nMenu item added.\n";
		
	}
	else {cout << "Invalid input or choice\n";}
	//---------------------------------------End C3---------------------------------------
}
